package com.gree.flowable.app.services.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.flowable.app.mapper.FlowableTaskMapper;
import com.gree.flowable.app.pojo.ex.HandleNodeEx;
import com.gree.flowable.app.pojo.model.*;
import com.gree.flowable.app.pojo.vo.FlowNodeVO;
import com.gree.flowable.app.pojo.vo.ReturnVO;
import com.gree.flowable.app.pojo.vo.SolvedTaskVO;
import com.gree.flowable.app.pojo.vo.TaskVO;
import com.gree.flowable.app.services.BaseProcessService;
import com.gree.flowable.app.services.IFlowableBpmnModelService;
import com.gree.flowable.app.services.IFlowableTaskService;
import com.gree.flowable.app.tools.constants.CommentTypeEnum;
import com.gree.flowable.app.tools.constants.FlowConstant;
import com.gree.flowable.app.tools.constants.NextNodeType;
import com.gree.flowable.app.tools.constants.ReturnCode;
import com.gree.flowable.app.tools.utils.StringSplitUtil;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.cmmn.editor.json.converter.util.CollectionUtils;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.idm.api.User;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class IFlowableTaskServiceImpl extends BaseProcessService implements IFlowableTaskService {
    @Autowired
    private FlowableTaskMapper flowableTaskMapper;
    @Autowired
    private IFlowableBpmnModelService iFlowableBpmnModelService;

    @Override
    public PagerModel<TaskVO> getApplyingTasks(QueryApplyMO params, Query query) {
        Page<TaskVO> page = new Page<>(query.getPageNum(), query.getPageSize());
        IPage<TaskVO> tasks = flowableTaskMapper.getApplyingTasks(page, params);
        return new PagerModel<>(tasks);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public ReturnVO<String> complete(CompleteTaskMO params) {
        ReturnVO<String> returnVO = null;
        String type = params.getType() == null ? CommentTypeEnum.SP.toString() : params.getType();
        if (StringUtils.isNotBlank(params.getBusinessKey())
                && StringUtils.isNotBlank(params.getTaskId())) {
            //1.查看当前任务是存在 TaskEntity 继承Task的接口
            TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(params.getTaskId()).singleResult();
            String currentNode = taskEntity.getTaskDefinitionKey();

            switch (params.getNextType()) {
                case NextNodeType.END:
                    break;
                case NextNodeType.DIRECT:
                    break;
                default:
                    if(params.getHandleArray().length == 0){
                        return new ReturnVO<>(ReturnCode.FAIL, "未输入下一节点信息！");
                    }else {
                        HandleNodeEx[] handleArray = params.getHandleArray();
                        for(int i = 0; i < handleArray.length; i++){
                            params.getVariables().put(currentNode + "_next", handleArray[i].getNode());
                            if(!("S999".equals(handleArray[i].getNode())) && !CommentTypeEnum.BH.name().equals(type)){
                                String assigns = handleArray[i].getAssign();
                                if (org.apache.commons.lang.StringUtils.isEmpty(assigns)){
                                    return new ReturnVO<>(ReturnCode.FAIL, "未选择审批人！");
                                }
                                params.getVariables().put(handleArray[i].getNode() + "_assignee", assigns);
                            }
                        }
                    }
            }

            if (taskEntity != null) {
                String taskId = params.getTaskId();
                //2.委派处理  pending 等待 暂停 resolved 处理；下定决心  delegation 委派
                if (DelegationState.PENDING.equals(taskEntity.getDelegationState())) {
                    //2.1生成历史记录（子任务）
                    TaskEntity task = this.createSubTask(taskEntity, params.getUserCode());
                    taskService.complete(task.getId());
                    taskId = task.getId();
                    //2.2执行委派
                    taskService.resolveTask(params.getTaskId(), params.getVariables());
                    returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "委派执行成功！");
                } else {
                    //3.1修改执行人 其实我这里就相当于签收了
//                    taskService.setAssignee(params.getTaskId(), null);
                    taskService.setAssignee(params.getTaskId(), params.getUserCode());
                    //3.2执行任务
                    taskService.complete(params.getTaskId(), params.getVariables());
                    //4.处理加签父任务
                    String parentTaskId = taskEntity.getParentTaskId();
                    if (StringUtils.isNotBlank(parentTaskId)) {
                        String tableName = managementService.getTableName(TaskEntity.class);
                        String sql = "select count(1) from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
                        long subTaskCount = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count();
                        if (subTaskCount == 0) {
                            Task task = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                            //处理前后加签的任务
                            taskService.resolveTask(parentTaskId);
                            if (FlowConstant.AFTER_ADDSIGN.equals(task.getScopeType())) {
                                taskService.complete(parentTaskId);
                            }
                        }
                    }
                    returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "审批成功！");
                }
                //5.生成审批意见
                this.addComment(taskId, params.getUserCode(), taskEntity.getProcessInstanceId(), type, params.getMessage());
            } else {
                returnVO = new ReturnVO<>(ReturnCode.FAIL, "没有此任务，请确认!");
            }
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "请输入正确的参数!");
        }
        return returnVO;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public ReturnVO<String> jumpTask(CompleteTaskMO compleVo, String targetNodeId) {
        ReturnVO returnVO = null;
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(compleVo.getBusinessKey()).singleResult();
        if (processInstance != null) {
            // 1、添加审批记录
            this.addComment(compleVo.getTaskId(), compleVo.getUserCode(), processInstance.getId(), CommentTypeEnum.CXTJ.toString(),
                    compleVo.getMessage());
            String processInstanceId = processInstance.getId();
            // 2、执行终止
            List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
            List<String> executionIds = new ArrayList<>();
            executions.forEach(execution -> executionIds.add(execution.getId()));
            // 清除跳转节点 流程跳转
            taskService.removeVariable(compleVo.getTaskId(), "jumpNodeKey");
            this.moveExecutionsToSingleActivityId(executionIds, targetNodeId);
            returnVO = new ReturnVO(ReturnCode.SUCCESS, "跳转成功！");
        } else {
            returnVO = new ReturnVO(ReturnCode.FAIL, "不存在运行的流程实例,请确认!");
        }
        return returnVO;
    }

    @Override
    public PagerModel<SolvedTaskVO> getApplyedTasks(QueryApplyMO params, Query query) {
        Page<SolvedTaskVO> page = new Page<>(query.getPageNum(), query.getPageSize());
        IPage<SolvedTaskVO> applyedTasks = flowableTaskMapper.getApplyedTasks(page, params);
        applyedTasks.getRecords().forEach(taskVo -> {
            String processInstanceId = taskVo.getProcessInstanceId();
            taskVo.setCurrentTaskState(this.getCurrentNodeState(processInstanceId));
        });
        return new PagerModel<>(applyedTasks);
    }


    @Override
    public List<User> getApprovers(String processInstanceId) {
        List<User> users = new ArrayList<>();
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(task -> {
                if (StringUtils.isNotBlank(task.getAssignee())) {
                    //1.审批人ASSIGNEE_是用户id
                    User user = identityService.createUserQuery().userId(task.getAssignee()).singleResult();
                    if (user != null) {
                        users.add(user);
                    }
                    //2.审批人ASSIGNEE_是组id
                    List<User> gusers = identityService.createUserQuery().memberOfGroup(task.getAssignee()).list();
                    if (org.flowable.editor.language.json.converter.util.CollectionUtils.isNotEmpty(gusers)) {
                        users.addAll(gusers);
                    }
                } else {
                    List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                    if (org.flowable.editor.language.json.converter.util.CollectionUtils.isNotEmpty(identityLinks)) {
                        identityLinks.forEach(identityLink -> {
                            //3.审批人ASSIGNEE_为空,用户id
                            if (StringUtils.isNotBlank(identityLink.getUserId())) {
                                User user = identityService.createUserQuery().userId(identityLink.getUserId()).singleResult();
                                if (user != null) {
                                    users.add(user);
                                }
                            } else {
                                //4.审批人ASSIGNEE_为空,组id
                                List<User> gusers = identityService.createUserQuery().memberOfGroup(identityLink.getGroupId()).list();
                                if (org.flowable.editor.language.json.converter.util.CollectionUtils.isNotEmpty(gusers)) {
                                    users.addAll(gusers);
                                }
                            }
                        });
                    }
                }
            });
        }
        return null;
    }

    @Override
    public List<Map> getApproversAndTaskNode(String processInstanceId) {
        ArrayList<Map> result = new ArrayList<>();
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(task -> {
                if (StringUtils.isNotBlank(task.getAssignee())) {
                    Map<Object, Object> map = new HashMap<>();
                    map.put("user", task.getAssignee());
                    map.put("nodeName", task.getName());
                    result.add(map);
                }else {
                    List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                    if (CollectionUtils.isNotEmpty(identityLinks)) {
                        identityLinks.forEach(identityLink -> {
                            //3.审批人ASSIGNEE_为空,用户id
                            if (StringUtils.isNotBlank(identityLink.getUserId())) {
                                Map<Object, Object> map = new HashMap<>();
                                map.put("user", identityLink.getUserId());
                                map.put("nodeName", task.getName());
                                result.add(map);
                            } else {

                            }
                        });
                    }
                }
            });
        }
        return result;
    }

    @Override
    public ReturnVO<String> turnTask(TurnTaskMO turnTaskVo) {
        ReturnVO<String> returnVO = null;
        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().taskId(turnTaskVo.getTaskId()).singleResult();
        if (currTask != null) {
            String instanceId = currTask.getProcessInstanceId();
            //1.生成历史记录
            TaskEntity task = this.createSubTask(currTask, turnTaskVo.getUserCode());
            //2.添加审批意见
            this.addComment(task.getId(), turnTaskVo.getUserCode(), instanceId, CommentTypeEnum.ZB.toString(), turnTaskVo.getMessage());
            taskService.complete(task.getId());
            //3.转办
            taskService.setAssignee(turnTaskVo.getTaskId(), turnTaskVo.getTurnToUserId());
            taskService.setOwner(turnTaskVo.getTaskId(), turnTaskVo.getUserCode());
            returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "转办成功");
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "没有运行时的任务实例,请确认!");
        }
        return returnVO;
    }

    @Override
    public ReturnVO<String> delegateTask(DelegateTaskMO delegateTaskVo) {
        ReturnVO<String> returnVO = null;
        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().taskId(delegateTaskVo.getTaskId()).singleResult();
        if (currTask != null) {
            //1.添加审批意见
            this.addComment(delegateTaskVo.getTaskId(), delegateTaskVo.getUserCode(), currTask.getProcessInstanceId(), CommentTypeEnum.WP.toString(), delegateTaskVo.getMessage());
            //2.设置审批人就是当前登录人
            taskService.setAssignee(delegateTaskVo.getTaskId(), delegateTaskVo.getUserCode());
            //3.执行委派
            taskService.delegateTask(delegateTaskVo.getTaskId(), delegateTaskVo.getDelegateUserCode());
            returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "委派成功");
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "没有运行时的任务实例,请确认!");
        }
        return returnVO;
    }

    /**
     * @param claimTaskVo
     * @return
     * @Title: 签收
     * @Description: 也可以用 taskService.setAssignee(taskId, userCode)
     * taskService.addCandicateUser(taskId, userCode1);  设置候选人，在没有assignee的时候，他们都可以看到这张单
     */
    @Override
    public ReturnVO<String> claimTask(ClaimTaskMO claimTaskVo) {
        ReturnVO<String> returnVO = null;
        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().taskId(claimTaskVo.getTaskId()).singleResult();
        if (currTask != null) {
            //1.添加审批意见
//            this.addComment(claimTaskVo.getTaskId(), claimTaskVo.getProcessInstanceId(), CommentTypeEnum.QS.toString(), claimTaskVo.getMessage());
            //2.签收
            taskService.claim(claimTaskVo.getTaskId(), claimTaskVo.getUserCode());
            returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "签收成功");
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "签收失败");
        }
        return returnVO;
    }

    @Override
    public ReturnVO<String> unClaimTask(ClaimTaskMO claimTaskVo) {
        ReturnVO<String> returnVO = null;
        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().taskId(claimTaskVo.getTaskId()).singleResult();
        if (currTask != null) {
            //1.添加审批意见
//            this.addComment(claimTaskVo.getTaskId(), claimTaskVo.getProcessInstanceId(), CommentTypeEnum.QS.toString(), claimTaskVo.getMessage());
            List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(claimTaskVo.getTaskId());
            boolean flag = false;
            if (org.flowable.editor.language.json.converter.util.CollectionUtils.isNotEmpty(identityLinks)) {
                for (IdentityLink link : identityLinks) {
                    if (IdentityLinkType.CANDIDATE.equals(link.getType())) {
                        flag = true;
                        break;
                    }
                }
            }
            //2.反签收
            if (flag) {
                taskService.claim(claimTaskVo.getTaskId(), null);
                returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "反签收成功");
            } else {
                returnVO = new ReturnVO<>(ReturnCode.FAIL, "由于没有候选人或候选组,会导致任务无法认领,请确认.");
            }
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "反签收失败");
        }
        return returnVO;
    }

    @Override
    public ReturnVO<String> beforeAddSignTask(AddSignTaskMO addSignTaskVo) {
        return this.addSignTask(addSignTaskVo, false);
    }

    @Override
    public ReturnVO<String> afterAddSignTask(AddSignTaskMO addSignTaskVo) {
        return this.addSignTask(addSignTaskVo, true);
    }

    @Override
    public ReturnVO<String> addSignTask(AddSignTaskMO addSignTaskVo, Boolean flag) {
        ReturnVO<String> returnVO = null;
        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery().taskId(addSignTaskVo.getTaskId()).singleResult();
        //1.把当前的节点设置为空
        if (taskEntity != null) {
            //如果是加签再加签
            String parentTaskId = taskEntity.getParentTaskId();
            if (StringUtils.isBlank(parentTaskId)) {
                taskEntity.setOwner(addSignTaskVo.getUserCode());
                taskEntity.setAssignee(null);
                taskEntity.setCountEnabled(true);
                if (flag) {
                    taskEntity.setScopeType(FlowConstant.AFTER_ADDSIGN);
                } else {
                    taskEntity.setScopeType(FlowConstant.BEFORE_ADDSIGN);
                }
                //1.2 设置任务为空执行者
                taskService.saveTask(taskEntity);
            }
            //2.添加加签数据
            this.createSignSubTasks(addSignTaskVo, taskEntity);
            //3.添加审批意见
            String type = flag ? CommentTypeEnum.HJQ.toString() : CommentTypeEnum.QJQ.toString();
            this.addComment(addSignTaskVo.getTaskId(), addSignTaskVo.getUserCode(), taskEntity.getProcessInstanceId(),
                    type, addSignTaskVo.getMessage());
            String message = flag ? "后加签成功" : "前加签成功";
            returnVO = new ReturnVO<>(ReturnCode.SUCCESS, message);
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "不存在任务实例，请确认!");
        }
        return returnVO;
    }

    /**
     * 创建加签子任务
     *
     * @param signVo     加签参数
     * @param taskEntity 父任务
     */
    private void createSignSubTasks(AddSignTaskMO signVo, TaskEntity taskEntity) {
        if (CollectionUtils.isNotEmpty(signVo.getSignPersoneds())) {
            String parentTaskId = taskEntity.getParentTaskId();
            if (StringUtils.isBlank(parentTaskId)) {
                parentTaskId = taskEntity.getId();
            }
            String finalParentTaskId = parentTaskId;
            //1.创建被加签人的任务列表
            signVo.getSignPersoneds().forEach(userCode -> {
                if (StringUtils.isNotBlank(userCode)) {
                    this.createSubTask(taskEntity, finalParentTaskId, userCode);
                }
            });
            String taskId = taskEntity.getId();
            if (StringUtils.isBlank(taskEntity.getParentTaskId())) {
                //2.创建加签人的任务并执行完毕
                Task task = this.createSubTask(taskEntity, finalParentTaskId, signVo.getUserCode());
                taskId = task.getId();
            }
            Task taskInfo = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (null != taskInfo) {
                taskService.complete(taskId);
            }
            //如果是候选人，需要删除运行时候选表种的数据。
            long candidateCount = taskService.createTaskQuery().taskId(parentTaskId).taskCandidateUser(signVo.getUserCode()).count();
            if (candidateCount > 0) {
                taskService.deleteCandidateUser(parentTaskId, signVo.getUserCode());
            }
        }
    }

    @Override
    public List<FlowNodeVO> getBackNodesByProcessInstanceId(String processInstanceId, String taskId) {
        List<FlowNodeVO> backNods = new ArrayList<>();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
        String currActId = taskEntity.getTaskDefinitionKey();
        //获取运行节点表中usertask
        String sql = "select t.* from act_ru_actinst t where t.ACT_TYPE_ = 'userTask' " +
                " and t.PROC_INST_ID_=#{processInstanceId} and t.END_TIME_ is not null ";
        List<ActivityInstance> activityInstances = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                .parameter("processInstanceId", processInstanceId)
                .list();
        //获取运行节点表的parallelGateway节点并去重 会签会有多条??? 预留难点
        sql = "SELECT a.* FROM  (SELECT t.ID_, t.REV_,t.PROC_DEF_ID_,t.PROC_INST_ID_,t.EXECUTION_ID_,t.ACT_ID_, t.TASK_ID_, t.CALL_PROC_INST_ID_, t.ACT_NAME_, t.ACT_TYPE_, " +
                " t.ASSIGNEE_, t.START_TIME_, t.END_TIME_, t.DURATION_, t.DELETE_REASON_, t.TENANT_ID_" +
                " FROM  act_ru_actinst t WHERE t.ACT_TYPE_ = 'parallelGateway' AND t.PROC_INST_ID_ = #{processInstanceId} and t.END_TIME_ is not null" +
                " and t.ACT_ID_ <> #{actId} ) a," +
                " (SELECT t.act_id_,max(t.END_TIME_) AS END_TIME_ FROM act_ru_actinst t WHERE t.ACT_TYPE_ = 'parallelGateway' AND t.PROC_INST_ID_ = #{processInstanceId}" +
                " and t.END_TIME_ is not null GROUP BY t.act_id_ )b where a.act_id_ = b.act_id_ and a.END_TIME_ = b.END_TIME_";
        List<ActivityInstance> parallelGatewaies = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                .parameter("processInstanceId", processInstanceId)
                .parameter("actId", currActId)
                .list();
        //排序
        if (CollectionUtils.isNotEmpty(parallelGatewaies)) {
            activityInstances.addAll(parallelGatewaies);
            activityInstances.sort(Comparator.comparing(ActivityInstance::getEndTime));
        }
        //分组节点
        int count = 0;
        Map<ActivityInstance, List<ActivityInstance>> parallelGatewayUserTasks = new HashMap<>();
        List<ActivityInstance> userTasks = new ArrayList<>();
        ActivityInstance currActivityInstance = null;
        for (ActivityInstance activityInstance : activityInstances) {
            if (BpmnXMLConstants.ELEMENT_GATEWAY_PARALLEL.equals(activityInstance.getActivityType())) {
                count++;
                if (count % 2 != 0) {
                    List<ActivityInstance> datas = new ArrayList<>();
                    currActivityInstance = activityInstance;
                    parallelGatewayUserTasks.put(currActivityInstance, datas);
                }
            }
            if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) {
                if (count % 2 == 0) {
                    userTasks.add(activityInstance);
                } else {
                    if (parallelGatewayUserTasks.containsKey(currActivityInstance)) {
                        parallelGatewayUserTasks.get(currActivityInstance).add(activityInstance);
                    }
                }
            }
        }
        //组装人员名称
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId).finished().list();
        Map<String, List<HistoricTaskInstance>> taskInstanceMap = new HashMap<>();
        List<String> userCodes = new ArrayList<>();
        historicTaskInstances.forEach(historicTaskInstance -> {
            userCodes.add(historicTaskInstance.getAssignee());
            String taskDefinitionKey = historicTaskInstance.getTaskDefinitionKey();
            if (taskInstanceMap.containsKey(historicTaskInstance.getTaskDefinitionKey())) {
                taskInstanceMap.get(taskDefinitionKey).add(historicTaskInstance);
            } else {
                List<HistoricTaskInstance> tasks = new ArrayList<>();
                tasks.add(historicTaskInstance);
                taskInstanceMap.put(taskDefinitionKey, tasks);
            }
        });
        //组装usertask的数据
        List<User> userList = identityService.createUserQuery().userIds(userCodes).list();
        Map<String, String> activityIdUserNames = this.getApplyers(processInstanceId, userList, taskInstanceMap);
        if (CollectionUtils.isNotEmpty(userTasks)) {
            userTasks.forEach(activityInstance -> {
                FlowNodeVO node = new FlowNodeVO();
                node.setNodeId(activityInstance.getActivityId());
                node.setNodeName(activityInstance.getActivityName());
                node.setEndTime(activityInstance.getEndTime());
                if (activityInstance.getActivityId().equals(FlowConstant.FLOW_SUBMIT_NODE)) {
                    node.setUserCode(processInstance.getStartUserId());
                } else {
                    node.setUserCode(activityInstance.getAssignee());
                }
                node.setUserName(activityIdUserNames.get(activityInstance.getActivityId()));
                backNods.add(node);
            });
        }
        //组装会签节点数据
        if (MapUtils.isNotEmpty(taskInstanceMap)) {
            parallelGatewayUserTasks.forEach((activity, activities) -> {
                FlowNodeVO node = new FlowNodeVO();
                node.setNodeId(activity.getActivityId());
                node.setEndTime(activity.getEndTime());
                StringBuffer nodeNames = new StringBuffer("会签:");
                StringBuffer userNames = new StringBuffer("审批人员:");
                StringBuffer assigneeCode = new StringBuffer("");
                if (CollectionUtils.isNotEmpty(activities)) {
                    activities.forEach(activityInstance -> {
                        nodeNames.append(activityInstance.getActivityName()).append(",");
                        userNames.append(activityIdUserNames.get(activityInstance.getActivityId())).append(",");
                        assigneeCode.append(activityInstance.getAssignee()).append(",");
                    });
                    node.setNodeName(nodeNames.deleteCharAt(nodeNames.length() - 1).toString());
                    node.setUserName(userNames.deleteCharAt(userNames.length() - 1).toString());
                    node.setUserCode(assigneeCode.deleteCharAt(assigneeCode.length() - 1).toString());
                    backNods.add(node);
                }
            });
        }
        //去重合并
        List<FlowNodeVO> datas = backNods.stream().collect(
                Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(nodeVo -> nodeVo.getNodeId()))), ArrayList::new));

        //排序
        datas.sort(Comparator.comparing(FlowNodeVO::getEndTime));
        return datas;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public ReturnVO<String> backToStepTask(BackTaskMO backTaskVo) {
        ReturnVO<String> returnVO = null;
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(backTaskVo.getTaskId()).singleResult();
        //1.把当前的节点设置为空
        if (taskEntity != null) {
            String instanceId = taskEntity.getProcessInstanceId();
            //2.设置审批人
            taskEntity.setAssignee(backTaskVo.getUserCode());
            taskService.saveTask(taskEntity);

            if (backTaskVo.isJump()) {
                // 需要跳转
                taskService.setVariable(backTaskVo.getTaskId(), "jumpNodeKey", taskEntity.getTaskDefinitionKey());
                taskService.setVariable(backTaskVo.getTaskId(), "jumpNodeName", taskEntity.getName());
//                taskService.setVariable(backTaskVo.getTaskId(), "jumpNodeName", taskEntity.get);
            }
            //3.添加回退意见
            this.addComment(backTaskVo.getTaskId(), backTaskVo.getUserCode(), instanceId, CommentTypeEnum.HT.toString(), backTaskVo.getMessage());
            //4.处理提交人节点
            FlowNode distActivity = iFlowableBpmnModelService.findFlowNodeByActivityId(taskEntity.getProcessDefinitionId(), backTaskVo.getBackTarget());
            if (distActivity != null) {
                if (FlowConstant.FLOW_SUBMIT_NODE.equals(distActivity.getId())) {
                    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(taskEntity.getProcessInstanceId()).singleResult();
                    runtimeService.setVariable(instanceId, FlowConstant.FLOW_SUBMITTER_VAR, processInstance.getStartUserId());
                }
            }
            //5.删除节点
            this.deleteActivity(backTaskVo.getBackTarget(), taskEntity.getProcessInstanceId());
            List<String> executionIds = new ArrayList<>();
            //6.判断节点是不是子流程内部的节点
            if (iFlowableBpmnModelService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                    backTaskVo.getBackTarget())
                    && iFlowableBpmnModelService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                    taskEntity.getTaskDefinitionKey())) {
                //6.1 子流程内部驳回
                Execution executionTask = runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult();
                String parentId = executionTask.getParentId();
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(parentId).list();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                this.moveExecutionsToSingleActivityId(executionIds, backTaskVo.getBackTarget());
            } else {
                //6.2 普通驳回
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                this.moveExecutionsToSingleActivityId(executionIds, backTaskVo.getBackTarget());
            }
            returnVO = new ReturnVO<>(ReturnCode.SUCCESS, "回退成功!");
        } else {
            returnVO = new ReturnVO<>(ReturnCode.FAIL, "不存在任务实例,请确认!");
        }
        return returnVO;
    }

    private Map<String, String> getApplyers(String processInstanceId, List<User> userList, Map<String, List<HistoricTaskInstance>> taskInstanceMap) {
        Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, user -> user));
        Map<String, String> applyMap = new HashMap<>();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        taskInstanceMap.forEach((activityId, taskInstances) -> {
            StringBuffer applyers = new StringBuffer();
            StringBuffer finalApplyers = applyers;
            taskInstances.forEach(taskInstance -> {
                if (!taskInstance.getName().equals(FlowConstant.FLOW_SUBMITTER)) {
                    User user = userMap.get(taskInstance.getAssignee());
                    if (user != null) {
                        if (StringUtils.indexOf(finalApplyers.toString(), user.getDisplayName()) == -1) {
                            finalApplyers.append(user.getDisplayName()).append(",");
                        }
                    }
                } else {
                    String startUserId = processInstance.getStartUserId();
                    User user = identityService.createUserQuery().userId(startUserId).singleResult();
                    if (user != null) {
                        finalApplyers.append(user.getDisplayName()).append(",");
                    }
                }
            });
            if (applyers.length() > 0) {
                applyers = applyers.deleteCharAt(applyers.length() - 1);
            }
            applyMap.put(activityId, applyers.toString());
        });
        return applyMap;
    }

    /**
     * @Title: 设置状态和审批人
     */
    private void setStateApproper(SolvedTaskVO solvedTaskVo) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(solvedTaskVo.getProcessInstanceId())
                .singleResult();
        if (processInstance == null) {
            solvedTaskVo.setCurrentTaskState(0);
        } else {
            if (processInstance.isSuspended()) {
                solvedTaskVo.setCurrentTaskState(2);
            } else {
                List<Map> assigneeAndTaskNode = this.getApproversAndTaskNode(solvedTaskVo.getProcessInstanceId());
                String[] approvers = StringSplitUtil.createApprovers2(assigneeAndTaskNode);

                solvedTaskVo.setCurrentTaskState(1);
                solvedTaskVo.setApproverId(approvers[0]);
            }
        }
    }

    private int getCurrentNodeState(String processIntanceId){
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processIntanceId)
                .singleResult();
        if (processInstance == null) {
            return 0;
        } else {
            if (processInstance.isSuspended()) {
                return 2;
            } else {
                return 1;
            }
        }
    }
}
